#include "udpserver.h"

#include "reply.h"
#include "request.h"
#include "requestfactory.h"

#include <iostream>

namespace b2gdns { namespace udp {

	using boost::asio::ip::udp;

	Server::Server(boost::asio::io_service& io_service, short port)
		: io_service_(io_service),
		  socket_(io_service_, udp::endpoint(udp::v4(), port))
	{
		socket_.async_receive_from(
			boost::asio::buffer(data_, max_length), sender_endpoint_,
			std::bind(&Server::handle_receive_from, this,
				std::placeholders::_1, std::placeholders::_2));
	}

	void Server::handle_receive_from(boost::system::error_code error,
		std::size_t bytes_recvd)
	{
		if (!error && (bytes_recvd > 0))
		{
			std::cout << "Received request: ";
			std::unique_ptr<Request> request =
				RequestFactory::CreateRequest(data_, bytes_recvd);
			std::cout << *request << std::endl;
			std::unique_ptr<Reply> reply = request->execute();

			socket_.async_send_to(
				boost::asio::buffer(reply->operator boost::asio::const_buffer()), sender_endpoint_,
				std::bind(&Server::handle_send_to, this,
				std::placeholders::_1, std::placeholders::_2));
		}
		else
		{
			socket_.async_receive_from(
				boost::asio::buffer(data_, max_length), sender_endpoint_,
				std::bind(&Server::handle_receive_from, this,
				std::placeholders::_1, std::placeholders::_2));
		}
	}

	void Server::handle_send_to(boost::system::error_code error,
		std::size_t bytes_sent)
	{
		std::cout << "error: " << error << ", sent: " << bytes_sent << std::endl;
		socket_.async_receive_from(
			boost::asio::buffer(data_, max_length), sender_endpoint_,
			std::bind(&Server::handle_receive_from, this,
				std::placeholders::_1, std::placeholders::_2));
	}

}} // namespace b2gdns::udp
